package com.jilujia.web.controller;

import java.security.Principal;
import java.util.ArrayList;
import java.util.List;

import javax.validation.Valid;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.jilujia.domain.blog.Blog;
import com.jilujia.domain.blog.BlogCatalog;
import com.jilujia.domain.blog.BlogComment;
import com.jilujia.domain.blog.BlogTypeEnum;
import com.jilujia.domain.blog.service.BlogService;
import com.jilujia.domain.region.Region;
import com.jilujia.domain.region.service.RegionService;
import com.jilujia.domain.user.User;
import com.jilujia.domain.user.service.UserService;
import com.jilujia.framework.exception.BusinessException;
import com.jilujia.framework.exception.ForbiddenOperatorException;
import com.jilujia.framework.exception.ResourceNotFoundException;
import com.jilujia.framework.security.JilujiaUser;
import com.jilujia.web.json.BlogData;

@Controller
public class BlogController extends AbstractWebController {

	private static final Logger LOG = LoggerFactory.getLogger(BlogController.class);

	@Autowired
	private UserService userService;

	@Autowired
	private BlogService blogService;

	@Autowired
	private RegionService regionService;

	public BlogController() {
	}

	@RequestMapping(value = "/blogs", method = RequestMethod.GET)
	public String listBlogs(Model model) {

		List<Blog> blogList = blogService.findAllBlogList();
		model.addAttribute(blogList);

		return "blogs/list";
	}

	@RequestMapping(value = "/users/{userId}/blogs/{id}", method = RequestMethod.GET)
	public String showBlogDetail(@PathVariable Long userId, @PathVariable Long id, Model model) {

		// 检查Blog是否存在
		Blog blog = blogService.findBlog(id);
		if (blog == null) {
			throw new ResourceNotFoundException(id);
		}

		// 检查User是否存在
		User user = userService.findEnabledUser(userId);
		if (user == null) {
			throw new ResourceNotFoundException(userId);
		}

		// 检查Blog的创建人和User是否一致
		if (user.getId().longValue() != blog.getUserId().longValue()) {
			throw new ForbiddenOperatorException(id);
		}

		List<BlogComment> blogCommentList = blogService.findBlogCommentList(id);
		BlogComment blogComment = blogService.createNewBlogComment(blog);

		model.addAttribute(blog);
		model.addAttribute(user);
		model.addAttribute(blogCommentList);
		model.addAttribute(blogComment);

		return "blogs/blogdetail";
	}

	@RequestMapping(value = "/users/{userId}/blogs/edit/{id}", method = RequestMethod.GET)
	@Secured( { "ROLE_USER" })
	public String showEditBlogDetail(Principal currentUser, @PathVariable Long userId, @PathVariable Long id,
			Model model) {

		// 检查Blog是否存在
		Blog blog = blogService.findBlog(id);
		if (blog == null) {
			throw new ResourceNotFoundException(id);
		}
		// 检查user是否存在，同时检查当然user和user是否一致
		User user = findUserByCurrentUserAndUserId(currentUser, userId);
		// 检查Blog的创建人和User是否一致
		if (user.getId().longValue() != blog.getUserId().longValue()) {
			throw new ForbiddenOperatorException(id);
		}

		genarateBlogModel(userId, model, blog, user);

		return "blogs/blogedit";
	}

	@RequestMapping(value = "/users/{userId}/blogs/new", method = RequestMethod.GET)
	@Secured( { "ROLE_USER" })
	public String showNewBlogDetail(Principal currentUser, @PathVariable Long userId, Model model) {
		// 检查user是否存在，同时检查当然user和user是否一致
		User user = findUserByCurrentUserAndUserId(currentUser, userId);
		genarateBlogModel(userId, model, blogService.createNewBlog(), user);
		return "blogs/blogedit";
	}

	@RequestMapping(value = "/blogs/persistpost", method = RequestMethod.POST)
	@Secured( { "ROLE_USER" })
	public @ResponseBody
	BlogData persistBlogPost(Principal currentUser, @Valid Blog blog, BindingResult result) {

		return postBlog(currentUser, blog, result, false);
	}

	private void genarateBlogModel(Long userId, Model model, Blog blog, User user) {

		List<BlogCatalog> catalogList = blogService.findCatalogList(userId);
		List<Region> regionList = regionService.findAllRegions();

		model.addAttribute("catalogList", catalogList);
		model.addAttribute(regionList);
		model.addAttribute(BlogTypeEnum.values());
		model.addAttribute(blog);
		model.addAttribute(user);
	}

	@RequestMapping(value = "/blogs/persistdraft", method = RequestMethod.POST)
	@Secured( { "ROLE_USER" })
	public @ResponseBody
	BlogData persistBlogDraft(Principal currentUser, @Valid Blog blog, BindingResult result) {

		return postBlog(currentUser, blog, result, true);
	}

	private BlogData postBlog(Principal currentUser, Blog blog, BindingResult result, boolean isDraft) {
		if (result.hasErrors()) {
			BlogData blogData = new BlogData(1, result.getAllErrors(), null, null);
			return blogData;
		}

		JilujiaUser currentRealUser = findUserByCurrentUser(currentUser);

		try {
			blog = blogService.persistBlog(blog, currentRealUser.getUserId(), isDraft);
		} catch (BusinessException e) {

			List<ObjectError> messages = new ArrayList<ObjectError>();
			ObjectError error = new ObjectError("error", e.getMessage());
			messages.add(error);

			BlogData blogData = new BlogData(1, messages, null, null);
			return blogData;
		}
		BlogData blogData = new BlogData(0, null, blog.getUserId(), blog.getId());
		return blogData;
	}

	@RequestMapping(value = "/blogcomments/persist", method = RequestMethod.POST)
	@Secured( { "ROLE_USER" })
	public String persistBlogComment(Principal currentUser, @Valid BlogComment blogComment, BindingResult result) {

		// new blog comment
		if (result.hasErrors()) {
			return "blogs/blogdetail";
		}

		JilujiaUser currentRealUser = findUserByCurrentUser(currentUser);

		blogComment = blogService.persistBlogComment(blogComment, currentRealUser.getUserId());

		LOG.debug("blogComment:{}", blogComment.getBlog().getReplyCount());

		return "redirect:/users/" + blogComment.getBlog().getUserId() + "/blogs/" + blogComment.getBlog().getId();
	}

	@RequestMapping(value = "/users/{userId}/blogs", method = RequestMethod.GET)
	public String listUserBlogs(@PathVariable Long userId, Model model) {

		// 检查User是否存在
		User user = userService.findEnabledUser(userId);
		if (user == null) {
			throw new ResourceNotFoundException(userId);
		}

		List<Blog> blogList = blogService.findBlogList(userId);
		model.addAttribute(blogList);
		model.addAttribute(user);

		return "blogs/bloglist";
	}

	@RequestMapping(value = "/users/{userId}/blogs/cataloglist", method = RequestMethod.GET)
	@Secured( { "ROLE_USER" })
	public String listCatalog(Principal currentUser, @PathVariable Long userId, Model model) {

		// 检查user是否存在，同时检查当然user和user是否一致
		User user = findUserByCurrentUserAndUserId(currentUser, userId);
		model.addAttribute(user);

		List<BlogCatalog> catalogList = blogService.findCatalogList(userId);
		model.addAttribute(catalogList);
		return "blogs/cataloglist";
	}

}
